package org.threads.banktransactions;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.utils.Utils;

import java.util.LinkedList;
import java.util.List;

/**
 *
 */
public class Bank {

    private static final Logger LOGGER = LoggerFactory.getLogger(Bank.class);

    List<Account> accounts = new LinkedList<>();

    /**
     * @param from
     * @param to
     * @param amount
     */
    public void transfer(Account from, Account to, int amount) {

        Account first, second;

        //The following comparison is aimed on avoiding deadlocks
        if (from.compareTo(to) > 0) {
            first = from;
            second = to;
        } else {
            first = to;
            second = from;
        }

        try {
            first.lock();
            second.lock();

            from.withdraw(amount);

            try {
                //The aim of this sleep is to create conditions, under which
                //the integrity of the amount can be broken
                Thread.sleep(Utils.getRandom(0, 20));
            } catch (InterruptedException e) {
                LOGGER.error(e.toString());
            }

            to.deposit(amount);

        } finally {
            second.unlock();
            first.unlock();
        }

        LOGGER.info("Transfered!");
    }

    /**
     * @param acc
     */
    public void addAccount(Account acc) {
        accounts.add(acc);
    }

    /**
     * @return
     */
    public long calculateGeneralAmount() {

        long generalAmount = 0;
        for (Account account : accounts) {
            generalAmount += account.getAmount();
        }
        return generalAmount;
    }

    /**
     * @return
     */
    public List<Account> getAccounts() {
        return accounts;
    }

}
